package com.h819.core.web.jqgrid;

import com.opensymphony.xwork2.ActionSupport;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 本类及继承类中的变量，都会被 struts2 的请求参数自动赋值
 * </p>
 * <p>
 * 该类是所有需要返回json数据的Action的<b>抽象基类</b>。在展示数据时，使用了jQuery的插件jqGrid，
 * 它对返回的json数据格式有一定的要求。该基类就处理了这些统一的格式要求。 需要返回json格式数据被jqGrid使用的，应该继承该类。<br/>
 * <b><font color='red'>注意：所有子类应该实现以下get方法，并只简单的返回相应的属性值。</font></b>
 * <ul>
 * <li>{@link JsoBaseAction#getTotalPages()}</li>
 * <li>{@link JsoBaseAction#getCurPageNo()}</li>
 * <li>{@link JsoBaseAction#getTotalRecords()}</li>
 * <li>{@link JsoBaseAction#getDataRows()}</li>
 * </ul>
 * 之所以将这些get方法定义为抽象的，是因为struts2的json插件只会序列化Action类，而不会序列化其父类。
 * </p>
 * 
 * <p>
 * <font color='red'>
 * 继承该类的Action方法，除了搜索（它需要返回JSON数据，因此可以返回SUCCESS)，其他操作都应该返回null而不是SUCCESS之类的。
 * 这意味着struts配置中，result什么也不用配，即没有相应的视图资源——这是AJAX请求。 </font>
 * </p>
 * 
 * <p>
 * 该类定义了以下几个字段：totalPages、curPageNo、totalRecords和dataRows。
 * 这几个字段是jqGrid格式的要求，而此处是自定义的。因此，在配置jqGrid接收服务器 返回的数据格式时，应该配置成这几个名字，用 jsonReader
 * 参数指定。(因为默认名字不是这样的，默认名字为：page,total,records,rows） 当然，也可以通过@JSON注解来指定与默认一样的名字
 * </p>
 * 
 * <p>
 * 另外一个字段page，则是一个分页类。因为jqGrid会向服务器端传递分页参数，
 * 用一个分页类接收这些参数。同样，为使Struts能够为page赋值，需要修改jqGrid默认的分页参数名。
 * jqGrid默认分页名为：（默认定义在options参数中的prmNames数组中）
 * <ul>
 * <li>page->显示第几页</li>
 * <li>rows->每页显示几条记录</li>
 * <li>sidx->排序字段</li>
 * <li>sord->排序方式（asc/desc)</li>
 * </ul>
 * 应用中应该根据{@link com.polaris.jqgrid.util.Page}类中的定义设置。设置为：
 * prmNames:{rows:"page.pageSize"
 * ,page:"page.curPageNo",sort:"page.orderBy",order:"page.order"}
 * 
 * prmNames数组的默认值为： prmNames: {page:"page",rows:"rows", sort: "sidx",order:
 * "sord", search:"_search", nd:"nd", npage:null}
 * </p>
 * 
 * @author xuxinhua
 * @version 1.0
 */
@SuppressWarnings("unchecked")
public abstract class JqgridListBaseAction extends ActionSupport {
	private static final long serialVersionUID = 1L;

	// 该属性专门用于接收删除的数据的ID（主键）。注意，当支持一次删除多记录时，id的值是通过','号分隔的多个
	protected String id;

	// 以下属性用于序列化成json格式的数据。名称不能改。如果要改，客户端页面对应的地方也要改(jsonReader 参数)；
	// 或通过@JSON来指定序列化的名字
	/*
	 * ==== 本类及继承类中的参数变量，都会被 struts2 的请求参数自动赋值(strut2规定，必须有 get,set 方法才可以赋值)
	 * 
	 * ( jsonReader 中定义谁会被组装)
	 * 
	 * ==== totalPages，curPageNo，totalRecords，dataRows 四个变量会通过 struts-json
	 * 插件，组装为 json 结构，传递到客户端
	 */

	// 总页数
	protected long totalPages;
	// 当前页数
	protected int curPageNo;
	// 总记录数目
	protected long totalRecords;
	// 用于显示的记录集合,每个 map 是一条记录
	protected List<Map<String, Object>> dataRows = new ArrayList<Map<String, Object>>();
	// sidx,指示查询排序的条件，这是一个字符串，可能是数据库表字段或者是POJO对象的属性名。这需要程序来处理。
	protected String sidx;
	// sord,指示查询排序的方式，可能的值是ASC和DESC
	protected String sord;
	// search,用来指示是否是查询，值是true或者false。但是我测试了一下，比如这个例子中，刚开始访问页面的时候，search=false。这个时候不管是点击哪一个表头排序，执行的动作，后台接收到的都是false。如果点击一下Navigation工具条最左边的查询按钮，执行一次查询动作，这个时候，search就变成true了。包括之后，再去点击显示表头进行排序，其search的结果都是true了。有点怪异！！！
	// 所以是否进行了查询，还不能仅仅根据这个字段判断
	// ==================================================================
	// 以下几个 search 字段，在进行单字段 search 操作的时候，post 到服务器端的参数

	// 多字段，传递到后台的是字符串(有时间的时候，总结一下)
	protected String search;
	// 查询的字段名称
	protected String searchField;
	// 查询的字段值
	protected String searchString;
	// 查询的字段操作
	protected String searchOper;

	// nd,暂时没搞懂什么意思？
	protected String nd;
	// npage,暂时没搞懂什么意思？
	protected String npage;

	// 分页类
	// 应用中应该根据 page 类中的定义设置。设置为：
	// prmNames:{rows:"page.pageSize",page:"page.pageNo",sort:"page.orderBy",order:"page.order"}
	// 这样，page 中的变量会被自动赋值，page 工具类就可以直接使用了
	protected Page page = new Page();

	// prmNames 默认参数
	// {page:"page",rows:"rows", sort: "sidx",order: "sord", search:"_search",
	// nd:"nd", id:"id",oper:"oper",editoper:"edit",addoper:"add",deloper:"del"}

	// 定义为抽象方法，表示该方法必须被实现，否则客户端无法解析
	public JqgridListBaseAction() {
		super();
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getId() {
		return id;
	}

	public Page getPage() {
		return page;
	}

	public void setPage(Page page) {
		this.page = page;
	}

	public abstract long getTotalPages();

	public void setTotalPages(long totalPages) {
		this.totalPages = totalPages;
	}

	 public abstract int getCurPageNo();
	
	 public void setCurPageNo(int curPageNo) {
	 this.curPageNo = curPageNo;
	 }

	public abstract long getTotalRecords();

	public void setTotalRecords(long totalRecords) {
		this.totalRecords = totalRecords;
	}

	/**
	 * 注意该方法的返回值：List。实际上包含了实际的数据， 而这些数据是放在Map<String, Object>中的。
	 * 因而，子类在action方法如：execute中，应该构建一个 Map<String, Object>对象，将数据放入其中，并把该对象放入
	 * List中。
	 * 
	 * @return
	 */
	public abstract List<Map<String, Object>> getDataRows();

	public void setDataRows(List<Map<String, Object>> dataRows) {
		this.dataRows = dataRows;
	}

	public String getSearch() {
		return search;
	}

	public void setSearch(String search) {
		this.search = search;
	}

	public String getSearchField() {
		return searchField;
	}

	public void setSearchField(String searchField) {
		this.searchField = searchField;
	}

	public String getSearchString() {
		return searchString;
	}

	public void setSearchString(String searchString) {
		this.searchString = searchString;
	}

	public String getSearchOper() {
		return searchOper;
	}

	public void setSearchOper(String searchOper) {
		this.searchOper = searchOper;
	}

	/**
	 * 判断是否进行了 search 操作。如果出现bug，查找是否需要判断 null 情况
	 * 
	 * @return
	 */
	public boolean isSearch() {

		if (this.getSearch() != null)
			return this.getSearch().equals("true")
					&& !this.getSearchField().equals("")
					&& !this.getSearchString().equals("")
					&& !this.getSearchOper().equals("");

		else
			return false;

	}
}
